﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

namespace NGIS
{
    namespace Model
    {
        public class ModelRuntime : IModelRuntime
        {
            private string mName;
            private string mVersion;
            private string mEntry;
            private string mBaseDirectory;
            
			private List<HardwareRequirement> mHardwareRequirementList = new List<HardwareRequirement>();
			private List<SoftwareRequirement> mSoftwareRequirementList = new List<SoftwareRequirement>();
			private List<ModelAssembly> mModelAssemblyList = new List<ModelAssembly>();
			private List<SupportiveResource> mSupportiveResourceList = new List<SupportiveResource>();


            public bool loadFromXml(XmlElement pModelClassElement)
			{
				XmlElement runtimeEle = pModelClassElement.ChildNodes[2] as XmlElement;
				mName = runtimeEle.GetAttribute("name");
                mVersion = runtimeEle.GetAttribute("version");
                mBaseDirectory = runtimeEle.GetAttribute("baseDir");
                mEntry = runtimeEle.GetAttribute("entry");

				XmlElement hardwareConfigures = runtimeEle.ChildNodes[0] as XmlElement;
                XmlElement softwareConfigures = runtimeEle.ChildNodes[1] as XmlElement;
                XmlElement modelAssemblyConfigures = runtimeEle.ChildNodes[2] as XmlElement;
                XmlElement supportiveConfigures = runtimeEle.ChildNodes[3] as XmlElement;

                foreach (var item in hardwareConfigures.ChildNodes)
				{
                    XmlElement childEle = item as XmlElement;
					HardwareRequirement temp_requirement;
					temp_requirement.requirementKey = childEle.GetAttribute("key");
                    temp_requirement.requirementValue = childEle.GetAttribute("value");
                    mHardwareRequirementList.Add(temp_requirement);
				}
                
                foreach (var item in softwareConfigures.ChildNodes)
				{
                    XmlElement childEle = item as XmlElement;
                    SoftwareRequirement temp_requirement = new SoftwareRequirement();
                    temp_requirement.requirementKey = childEle.GetAttribute("key");
                    temp_requirement.requirementValue = childEle.GetAttribute("value");
                    temp_requirement.requirementPlatform = childEle.GetAttribute("platform");
                    mSoftwareRequirementList.Add(temp_requirement);
				}
                
                foreach (var item in modelAssemblyConfigures.ChildNodes)
				{
                    XmlElement childEle = item as XmlElement;
					ModelAssembly temp_requirement;
                    temp_requirement.assemblyName = childEle.GetAttribute("name");
                    temp_requirement.assemblyPath = childEle.GetAttribute("path");
                    mModelAssemblyList.Add(temp_requirement);
				}
                
                foreach (var item in supportiveConfigures.ChildNodes)
				{
                    XmlElement childEle = item as XmlElement;
					SupportiveResource temp_requirement;
                    temp_requirement.resourceType = childEle.GetAttribute("type");
                    temp_requirement.resourceName = childEle.GetAttribute("name");
					mSupportiveResourceList.Add(temp_requirement);
				}

				return true;
			}

			public bool formatToXml(XmlElement pModelClassElement)
			{
                XmlDocument doc = pModelClassElement.OwnerDocument;
				XmlElement runtimeEle = doc.CreateElement("Runtime");
				runtimeEle.SetAttribute("name", mName);
				runtimeEle.SetAttribute("version", mVersion);
				runtimeEle.SetAttribute("baseDir", mBaseDirectory);
				runtimeEle.SetAttribute("entry", mEntry);

                XmlElement hardwareConfigures = doc.CreateElement("HardwareConfigures");
                XmlElement softwareConfigures = doc.CreateElement("SoftwareConfigures");
                XmlElement modelAssemblyConfigures = doc.CreateElement("Assemblies");
                XmlElement supportiveConfigures = doc.CreateElement("SupportiveResources");

				for (int i=0; i<mHardwareRequirementList.Count; i++)
				{
                    XmlElement temp_ele = doc.CreateElement("Add");
					temp_ele.SetAttribute("key", mHardwareRequirementList[i].requirementKey);
					temp_ele.SetAttribute("value", mHardwareRequirementList[i].requirementValue);
					hardwareConfigures.AppendChild(temp_ele);
				}

				for (int i=0; i<mSoftwareRequirementList.Count; i++)
				{
                    XmlElement temp_ele = doc.CreateElement("Add");
					temp_ele.SetAttribute("key", mSoftwareRequirementList[i].requirementKey);
					temp_ele.SetAttribute("value", mSoftwareRequirementList[i].requirementValue);
                    temp_ele.SetAttribute("platform", mSoftwareRequirementList[i].requirementPlatform);
                    softwareConfigures.AppendChild(temp_ele);
				}

				for (int i=0; i<mModelAssemblyList.Count; i++)
				{
                    XmlElement temp_ele = doc.CreateElement("Assembly");
					temp_ele.SetAttribute("name", mModelAssemblyList[i].assemblyName);
					temp_ele.SetAttribute("path", mModelAssemblyList[i].assemblyPath);
                    modelAssemblyConfigures.AppendChild(temp_ele);
				}

				for (int i=0; i<mSupportiveResourceList.Count; i++)
				{
                    XmlElement temp_ele = doc.CreateElement("Add");
					temp_ele.SetAttribute("type", mSupportiveResourceList[i].resourceType);
					temp_ele.SetAttribute("name", mSupportiveResourceList[i].resourceName);
                    supportiveConfigures.AppendChild(temp_ele);
				}

                runtimeEle.AppendChild(hardwareConfigures);
                runtimeEle.AppendChild(softwareConfigures);
                runtimeEle.AppendChild(modelAssemblyConfigures);
                runtimeEle.AppendChild(supportiveConfigures);

                pModelClassElement.AppendChild(runtimeEle);

				return true;
			}


            public string getName()
            {
                return mName;
            }

            public void setName(string pName)
            {
                mName = pName;
            }

            public string getVersion()
            {
                return mVersion;
            }

            public void setVersion(string pVersion)
            {
                mVersion = pVersion;
            }

            public string getEntry()
            {
                return mEntry;
            }

            public void setEntry(string pEntry)
            {
                mEntry = pEntry;
            }

            public string getBaseDirectory()
            {
                return mBaseDirectory;
            }

            public void setBaseDirectory(string pDirectory)
            {
                mBaseDirectory = pDirectory;
            }

            public bool addHardwareRequirement(ref HardwareRequirement pRequirement)
            {
                for (int i = 0; i < mHardwareRequirementList.Count; i++)
                {
                    if (mHardwareRequirementList[i].requirementKey == pRequirement.requirementKey &&
                        mHardwareRequirementList[i].requirementValue == pRequirement.requirementValue)
                    {
                        return false;
                    }
                }
                mHardwareRequirementList.Add(pRequirement);
                return true;
            }

            public bool addSoftwareRequirement(ref SoftwareRequirement pRequirement)
            {
                for (int i = 0; i < mSoftwareRequirementList.Count; i++)
                {
                    if (mSoftwareRequirementList[i].requirementKey == pRequirement.requirementKey &&
                        mSoftwareRequirementList[i].requirementValue == pRequirement.requirementValue)
                    {
                        return false;
                    }
                }
                mSoftwareRequirementList.Add(pRequirement);
                return true;
            }

            public bool addModelAssembly(ref ModelAssembly pRequirement)
            {
                for (int i = 0; i < mModelAssemblyList.Count; i++)
                {
                    if (mModelAssemblyList[i].assemblyName == pRequirement.assemblyName &&
                        mModelAssemblyList[i].assemblyPath == pRequirement.assemblyPath)
                    {
                        return false;
                    }
                }
                mModelAssemblyList.Add(pRequirement);
                return true;
            }

            public bool addSupportiveResource(ref SupportiveResource pRequirement)
            {
                for (int i = 0; i < mSupportiveResourceList.Count; i++)
                {
                    if (mSupportiveResourceList[i].resourceType == pRequirement.resourceType &&
                        mSupportiveResourceList[i].resourceName == pRequirement.resourceName)
                    {
                        return false;
                    }
                }
                mSupportiveResourceList.Add(pRequirement);
                return true;
            }

            public int getHardwareRequirementCount()
            {
                return mHardwareRequirementList.Count;
            }

            public int getSoftwareRequirementCount()
            {
                return mSoftwareRequirementList.Count;
            }

            public int getModelAssemblyCount()
            {
                return mModelAssemblyList.Count;
            }

            public int getSupportiveResourceCount()
            {
                return mSupportiveResourceList.Count;
            }

            public bool getHardwareRequirement(int idx, ref HardwareRequirement pRequirement)
            {
                if (idx < 0 || idx >= mHardwareRequirementList.Count) return false;
                pRequirement = mHardwareRequirementList[idx];
                return true;
            }

            public bool getSoftwareRequirement(int idx, ref SoftwareRequirement pRequirement)
            {
                if (idx < 0 || idx >= mSoftwareRequirementList.Count) return false;
                pRequirement = mSoftwareRequirementList[idx];
                return true;
            }

            public bool getModelAssembly(int idx, ref ModelAssembly pRequirement)
            {
                if (idx < 0 || idx >= mModelAssemblyList.Count) return false;
                pRequirement = mModelAssemblyList[idx];
                return true;
            }

            public bool getSupportiveResource(int idx, ref SupportiveResource pRequirement)
            {
                if (idx < 0 || idx >= mSupportiveResourceList.Count) return false;
                pRequirement = mSupportiveResourceList[idx];
                return true;
            }

            public bool removeHardwareRequirementref(HardwareRequirement pRequirement)
            {
                if (mHardwareRequirementList.Contains(pRequirement))
                {
                    mHardwareRequirementList.Remove(pRequirement);
                    return true;
                }
                return false;
            }

            public bool removeSoftwareRequirement(ref SoftwareRequirement pRequirement)
            {
                if (mSoftwareRequirementList.Contains(pRequirement))
                {
                    mSoftwareRequirementList.Remove(pRequirement);
                    return true;
                }
                return false;
            }

            public bool removeModelAssembly(ref ModelAssembly pRequirement)
            {
                if (mModelAssemblyList.Contains(pRequirement))
                {
                    mModelAssemblyList.Remove(pRequirement);
                    return true;
                }
                return false;
            }

            public bool removeSupportiveResource(ref SupportiveResource pRequirement)
            {
                if (mSupportiveResourceList.Contains(pRequirement))
                {
                    mSupportiveResourceList.Remove(pRequirement);
                    return true;
                }
                return false;
            }

            public bool removeHardwareRequirement(int idx)
            {
				if (idx<0 || idx>= mHardwareRequirementList.Count) return false;
                mHardwareRequirementList.RemoveAt(idx);
				return true;
            }

            public bool removeSoftwareRequirement(int idx)
            {
				if (idx<0 || idx>= mSoftwareRequirementList.Count) return false;
                mSoftwareRequirementList.RemoveAt(idx);
                return true;
            }

            public bool removeModelAssembly(int idx)
            {
				if (idx<0 || idx>= mModelAssemblyList.Count) return false;
                mModelAssemblyList.RemoveAt(idx);
				return true;
            }

            public bool removeSupportiveResource(int idx)
            {
				if (idx<0 || idx>= mSupportiveResourceList.Count) return false;
                mSupportiveResourceList.RemoveAt(idx);
				return true;
            }

            public bool compareOther(IModelRuntime pRuntime, ref string obj, ref string name)
            {
                if (mName != pRuntime.getName())
                {
                    obj = "Runtime";
                    name = "name";
                    return false;
                }
                if (mVersion != pRuntime.getVersion())
                {
                    obj = "Runtime";
                    name = "version";
                    return false;
                }
                if (mEntry != pRuntime.getEntry())
                {
                    obj = "Runtime";
                    name = "entry";
                    return false;
                }
                if (mBaseDirectory != pRuntime.getBaseDirectory())
                {
                    obj = "Runtime";
                    name = "baseDir";
                    return false;
                }

                if (mHardwareRequirementList.Count != pRuntime.getHardwareRequirementCount())
                {
                    obj = "HardwareConfigures";
                    name = "HardwareRequirementCount";
                    return false;
                }
                for (int i = 0; i < mHardwareRequirementList.Count; i++)
                {
                    HardwareRequirement temp_req1 = mHardwareRequirementList[i];
                    HardwareRequirement temp_req2 = new HardwareRequirement();
                    pRuntime.getHardwareRequirement(i, ref temp_req2);
                    if (temp_req1.compareOther(temp_req2) == false)
                    {
                        obj = "Hardware";
                        name = temp_req1.requirementKey + "<-->" + temp_req2.requirementKey;
                        return false;
                    }
                }
                if (mSoftwareRequirementList.Count != pRuntime.getSoftwareRequirementCount())
                {
                    obj = "SoftwareConfigures";
                    name = "SoftwareRequirementCount";
                    return false;
                }
                for (int i = 0; i < mSoftwareRequirementList.Count; i++)
                {
                    SoftwareRequirement temp_req1 = mSoftwareRequirementList[i];
                    SoftwareRequirement temp_req2 = new SoftwareRequirement();
                    pRuntime.getSoftwareRequirement(i, ref temp_req2);
                    if (temp_req1.compareOther(temp_req2) == false)
                    {
                        obj = "Software";
                        name = temp_req1.requirementKey + "<-->" + temp_req2.requirementKey;
                        return false;
                    }
                }
                if (mModelAssemblyList.Count != pRuntime.getModelAssemblyCount())
                {
                    obj = "Assemblies";
                    name = "AssemblyCount";
                    return false;
                }
                for (int i = 0; i < mModelAssemblyList.Count; i++)
                {
                    ModelAssembly temp_assembly1 = mModelAssemblyList[i];
                    ModelAssembly temp_assembly2 = new ModelAssembly();
                    pRuntime.getModelAssembly(i, ref temp_assembly2);
                    if (temp_assembly1.compareOther(temp_assembly2) == false)
                    {
                        obj = "Assembly";
                        name = temp_assembly1.assemblyName + "<-->" + temp_assembly2.assemblyName;
                        return false;
                    }
                }
                if (mSupportiveResourceList.Count != pRuntime.getSupportiveResourceCount())
                {
                    obj = "SupportiveResources";
                    name = "SupportiveResourceCount";
                    return false;
                }
                for (int i = 0; i < mSupportiveResourceList.Count; i++)
                {
                    SupportiveResource temp_res1 = mSupportiveResourceList[i];
                    SupportiveResource temp_res2 = new SupportiveResource();
                    pRuntime.getSupportiveResource(i, ref temp_res2);
                    if (temp_res1.compareOther(temp_res2) == false)
                    {
                        obj = "SupportiveResource";
                        name = temp_res1.resourceName + "<-->" + temp_res2.resourceName;
                        return false;
                    }
                }
                return true;
            }
        }
    }
}
